package com.rt.schedulenew.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.rt.schedulebase.dto.DictScheduleCycleDto;
import com.rt.schedulebase.dto.ExamScheduleDto;
import com.rt.schedulebase.entity.DictCommonUse;
import com.rt.schedulebase.entity.DictScheduleApm;
import com.rt.schedulebase.entity.DictScheduleCycle;
import com.rt.schedulebase.entity.commonentity.PageResultUtil;
import com.rt.schedulebase.mapper.DictScheduleApmMapper;
import com.rt.schedulebase.mapper.DictScheduleCycleMapper;
import com.rt.schedulebase.mapper.ExamScheduleMapper;
import com.rt.schedulenew.api.DictScheduleCycleService;
import com.rt.schedulenew.utils.global.BusinessException;
import com.rt.schedulenew.utils.global.ErrorCode;
import com.rt.schedulenew.utils.global.JsonResult;
import com.rt.schedulenew.utils.global.JsonResultUtil;
import com.rt.schedulenew.utils.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ProjectName: server
 * @Package: com.rt.schedulebase.service.impl
 * @ClassName: DictScheduleCycleServiceImpl
 * @Author: chendong
 * @Description: 号源周期
 * @Date: 2022/10/25 10:46
 * @Version: 1.0
 */
@Service
@Transactional
public class DictScheduleCycleServiceImpl implements DictScheduleCycleService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private DictScheduleCycleMapper cycleMapper;

    @Resource
    private DictScheduleApmMapper dictScheduleApmMapper;

    @Resource
    private ExamScheduleMapper examScheduleMapper;


    @Override
    public JsonResult getCycleToPage(DictScheduleCycleDto dto) {
        DictScheduleCycle dictScheduleCycle = new DictScheduleCycle();
        BeanUtils.copyProperties(dto,dictScheduleCycle);
        Page<DictCommonUse> page = new Page<>();
        if (dto.getPageNo() != null) {
            page = PageHelper.startPage(dto.getPageNo(), dto.getPageSize());
        }
        List<DictScheduleCycle> cYcleList = cycleMapper.selectCycle(dictScheduleCycle);
        JsonResult jsonResult = PageResultUtil.success(ErrorCode.SUCCESS.getValue(), cYcleList, page);
        return jsonResult;
    }

    @Override
    public JsonResult saveRangeJudge(DictScheduleCycle cycle) {
        if (cycle.getCycleType().equals("1") && (cycle.getDateStart().length() < 10 || cycle.getDateEnd().length() < 10)) {
            return JsonResultUtil.failure("周期日期有误");
        }
        if (cycle.getCycleType().equals("2") && (cycle.getDateStart().length() < 5 || cycle.getDateEnd().length() < 5)) {
            return JsonResultUtil.failure("周期日期有误");
        }
        if (StringUtils.isBlank(cycle.getDateStart()) || StringUtils.isBlank(cycle.getDateEnd())) {
            return JsonResultUtil.failure("号源周期为空");
        }
        if (StringUtils.isBlank(cycle.getExamClass())) {
            return JsonResultUtil.failure("检查类别为空");
        }
        if (StringUtils.isBlank(cycle.getQueueName())) {
            return JsonResultUtil.failure("队列名称为空");
        }
        if (StringUtils.isBlank(cycle.getCycleType())) {
            return JsonResultUtil.failure("周期类别为空");
        }
        try {
            boolean isCycle = cycleRangeJudge(cycle);
            if (!isCycle) {
                return JsonResultUtil.failure("您选择的号源周期重复");
            }
            DictScheduleCycle dictScheduleCycle = new DictScheduleCycle();
            BeanUtils.copyProperties(cycle,dictScheduleCycle);
            if (cycle.getId() != null) {
                DictScheduleCycle scheduleCycle = cycleMapper.selectById(cycle.getId());
                if (scheduleCycle == null) {
                    return JsonResultUtil.failure("您选择的号源周期已不存在！");
                }
                if (!scheduleCycle.getCycleType().equals(cycle.getCycleType())) {
                    return JsonResultUtil.failure("不允许更改周期类型！");
                }
                QueryWrapper<DictScheduleApm> wrapper = new QueryWrapper<>();
                wrapper.eq("QUEUE_NAME", scheduleCycle.getQueueName());
                wrapper.eq("DATE_START", scheduleCycle.getDateStart());
                wrapper.eq("DATE_END", scheduleCycle.getDateEnd());
                List<DictScheduleApm> dictScheduleApms = dictScheduleApmMapper.selectList(wrapper);
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                final Date[] newStartDate = {null};
                final Date[] newEndDate = {null};
                if (cycle.getCycleType().equals("1")) {
                    newStartDate[0] = df.parse(cycle.getDateStart());
                    newEndDate[0] = df.parse(cycle.getDateEnd());
                }
                dictScheduleApms.forEach(item -> {
                    ExamScheduleDto dto = examScheduleMapper.getApmMaxDateAndMinByApmCode(item.getApmCode());
                    if (dto != null) {
                        try {
                            Date minDate = df.parse(dto.getStartDate());
                            Date maxDate = df.parse(dto.getEndDate());
                            if (cycle.getCycleType().equals("2")) {
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
                                String dateMin = sdf.format(minDate);
                                String dateMax = sdf.format(maxDate);
                                newStartDate[0] = df.parse(dateMin + "-" + cycle.getDateStart());
                                newEndDate[0] = df.parse(dateMax + "-" + cycle.getDateEnd());
                            }
                            if ((!newStartDate[0].equals(minDate) || !newStartDate[0].before(minDate))
                                    || (!newEndDate[0].equals(maxDate) || !newEndDate[0].after(maxDate))) {
                                throw new BusinessException("修改失败，时段：【"+ item.getScheduleApm()+"】下[" + dto.getStartDate() + "]-[" + dto.getEndDate() + "]时间范围已有预约");
                            }
                        } catch (ParseException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
                cycleMapper.updateById(cycle);
                // 更新时段中的周期范围
                dictScheduleApms.forEach(item -> {
                    item.setDateStart(cycle.getDateStart());
                    item.setDateEnd(cycle.getDateEnd());
                    UpdateWrapper<DictScheduleApm> up = new UpdateWrapper<>();
                    up.eq("APM_CODE", item.getApmCode());
                    dictScheduleApmMapper.update(item, up);
                    // 判断是否为特殊时段，如果是则校验是否还在周期内若不在则删除
                    if (item.getScheduleDate() != null) {
                        Date technicalDate = null;
                        try {
                            technicalDate = df.parse(item.getScheduleDate());
                            if (cycle.getCycleType().equals("2")) {
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
                                String dateMin = sdf.format(technicalDate);
                                String dateMax = sdf.format(technicalDate);
                                newStartDate[0] = df.parse(dateMin + "-" + cycle.getDateStart());
                                newEndDate[0] = df.parse(dateMax + "-" + cycle.getDateEnd());
                            }
                        } catch (ParseException e) {
                            throw new RuntimeException(e);
                        }

                        if ((!item.getScheduleDate().equals(cycle.getDateStart()) || !item.getScheduleDate().equals(cycle.getDateEnd()))
                                && (technicalDate.after(newEndDate[0]) || technicalDate.before(newStartDate[0]))) {
                            dictScheduleApmMapper.delete(up);
                        }
                    }
                });
                return JsonResultUtil.success("保存成功");
            } else {
                List<DictScheduleCycle> dictScheduleCycles = cycleMapper.selectCycle(cycle);
                if (dictScheduleCycles != null && dictScheduleCycles.size() < 1) {
                    cycleMapper.save(cycle);
                    return JsonResultUtil.success("保存成功");
                } else {
                    return JsonResultUtil.failure("您选择新增的号源周期已存在！");
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            return JsonResultUtil.failure(e.getMessage());
        }
    }

    @Override
    public JsonResult getCycleList(DictScheduleCycle cycle) {
        DictScheduleCycle scheduleCycle = new DictScheduleCycle();
        scheduleCycle.setExamClass(cycle.getExamClass());
        scheduleCycle.setQueueName(cycle.getQueueName());
        List<DictScheduleCycle> dictScheduleCycles = cycleMapper.selectCycle(scheduleCycle);

        if (CollectionUtils.isEmpty(dictScheduleCycles)) {
            return JsonResultUtil.success("未设置号源周期");
        }

        ArrayList<DictScheduleCycleDto> dictScheduleCycleDtos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(dictScheduleCycles)) {
            for (DictScheduleCycle dictScheduleCycle : dictScheduleCycles) {
                DictScheduleCycleDto dictScheduleCycleDto = new DictScheduleCycleDto();
                try {
                    String dateStart = dictScheduleCycle.getDateStart();
                    String dateEnd = dictScheduleCycle.getDateEnd();
                    //String formatter = "yyyy-MM-dd";
                    if (StringUtils.isNotBlank(dictScheduleCycle.getCycleType()) && dictScheduleCycle.getCycleType().equals("2")) {
                        // 没有年份
                        // 是否跨年
                        boolean isPass = isNewYear(dateStart, dateEnd);
                        Calendar cale = Calendar.getInstance();
                        String currentYear = String.valueOf(cale.get(1));

                        dateStart = currentYear + "-" + dateStart;
                        dateEnd = currentYear + "-" + dateEnd;
                        if (isPass) {
                            throw new BusinessException("结束时间大于开始时间！");
                        }
                    }

                    Date startDate = DateUtil.parse(dateStart, DateUtil.FORMAT_DATE);
                    Date endDate = DateUtil.parse(dateEnd, DateUtil.FORMAT_DATE);
                    Date currentDate = new Date();

                    if (startDate.getTime() <= currentDate.getTime()
                            && endDate.getTime() >= currentDate.getTime()) {
                        dictScheduleCycleDto.setApmType("1");
                    }
                } catch (Exception e) {
                    logger.error("getCycleList:" + e.getMessage(), e);
                    e.printStackTrace();
                }
                BeanUtils.copyProperties(dictScheduleCycle,dictScheduleCycleDto);
                dictScheduleCycleDtos.add(dictScheduleCycleDto);
            }
            return JsonResultUtil.success("成功", dictScheduleCycleDtos);
        }
        return JsonResultUtil.success("未设置号源周期");
    }

    @Override
    public JsonResult deleteRangeJudge(DictScheduleCycle cycle) {
        if (cycle.getCycleType().equals("1") && (cycle.getDateStart().length() < 5 || cycle.getDateEnd().length() < 5)) {
            return JsonResultUtil.failure("周期日期有误");
        }
        if (StringUtils.isBlank(cycle.getDateStart()) || StringUtils.isBlank(cycle.getDateEnd())) {
            return JsonResultUtil.failure("号源周期为空");
        }
        if (StringUtils.isBlank(cycle.getExamClass())) {
            return JsonResultUtil.failure("检查类别为空");
        }
        if (StringUtils.isBlank(cycle.getQueueName())) {
            return JsonResultUtil.failure("队列名称为空");
        }
        if (StringUtils.isBlank(cycle.getQueueName())) {
            return JsonResultUtil.failure("队列名称为空");
        }
        if (StringUtils.isBlank(cycle.getCycleType())) {
            return JsonResultUtil.failure("周期类别为空");
        }
        int isSchedule = dictScheduleApmMapper.isScheduleCount(cycle);
        if (isSchedule > 0) {
            return JsonResultUtil.failure("该周期内已有预约记录，无法删除");
        }
        int deleteResult = cycleMapper.deleteById(cycle.getId());
        if (deleteResult == 1) {
            dictScheduleApmMapper.delForRegular(cycle);
            dictScheduleApmMapper.delForRange(cycle);
            return JsonResultUtil.success("删除成功");
        }
        return JsonResultUtil.failure("删除失败");
    }

    private boolean cycleRangeJudge(DictScheduleCycle dto) throws ParseException {
        boolean currentIsPass = false;
        if (dto.getCycleType().equals("2")) {
            currentIsPass = isNewYear(dto.getDateStart(), dto.getDateEnd());
            if (currentIsPass) {
                throw new BusinessException("结束时间大于开始时间！");
            }
        } else {
            Date inputBeginDate = DateUtil.parse(dto.getDateStart(), "yyyy-MM-dd");
            Date inputEndDate = DateUtil.parse(dto.getDateEnd(), "yyyy-MM-dd");
            if (inputBeginDate.after(inputEndDate)) {
                throw new BusinessException("结束时间大于开始时间！");
            }
        }




        DictScheduleCycle dictScheduleCycle = new DictScheduleCycle();
        dictScheduleCycle.setExamClass(dto.getExamClass());
        dictScheduleCycle.setQueueName(dto.getQueueName());
        List<DictScheduleCycle> cYcleList = cycleMapper.selectCycle(dictScheduleCycle);
        if (dto.getId() != null) {
            cYcleList = cYcleList.stream().filter(vo -> !vo.getId().equals(dto.getId())).collect(Collectors.toList());
        }
        if (cYcleList.size() < 1) {
            return true;
        }

        Calendar cale = Calendar.getInstance();
        String currentYear = String.valueOf(cale.get(1));
        String currentDateStart = dto.getDateStart();
        String currentDateEnd = dto.getDateEnd();

        List<DictScheduleApm> dsaList = new ArrayList<DictScheduleApm>();
        for (DictScheduleCycle cycle : cYcleList) {
            DictScheduleApm scheduleApm = new DictScheduleApm();
            if (StringUtils.isNotBlank(cycle.getCycleType()) && cycle.getCycleType().equals("2")) {
                scheduleApm.setDateStart(currentYear + "-" + cycle.getDateStart());
                scheduleApm.setDateEnd(currentYear + "-" + cycle.getDateEnd());
            } else {
                scheduleApm.setDateStart(cycle.getDateStart());
                scheduleApm.setDateEnd(cycle.getDateEnd());
            }
            dsaList.add(scheduleApm);
        }
        if (StringUtils.isNotBlank(dto.getCycleType()) && dto.getCycleType().equals("2")) {
            currentDateStart = currentYear + "-" + dto.getDateStart();
            currentDateEnd = currentYear + "-" + dto.getDateEnd();
            Date inputBeginDate = DateUtil.parse(currentDateStart, "yyyy-MM-dd");
            Date inputEndDate = DateUtil.parse(currentDateEnd, "yyyy-MM-dd");
            for (DictScheduleApm item : dsaList) {
                Date beginDate = DateUtil.parse(item.getDateStart(), "yyyy-MM-dd");
                Date endDate = DateUtil.parse(item.getDateEnd(), "yyyy-MM-dd");
                if (beginDate.before(inputBeginDate) && endDate.after(inputBeginDate)) {
                    return false;
                }
                if (endDate.after(inputEndDate) && beginDate.before(inputEndDate)) {
                    return false;
                }
                if (beginDate.equals(inputBeginDate)) {
                    return false;
                }
                if (endDate.equals(inputEndDate)) {
                    return false;
                }
            }
        }
        if (StringUtils.isNotBlank(dto.getCycleType()) && dto.getCycleType().equals("1")) {
            Date inputBeginDate = DateUtil.parse(dto.getDateStart(), "yyyy-MM-dd");
            Date inputEndDate = DateUtil.parse(dto.getDateEnd(), "yyyy-MM-dd");
            for (DictScheduleApm item : dsaList) {
                Date beginDate = DateUtil.parse(item.getDateStart(), "yyyy-MM-dd");
                Date endDate = DateUtil.parse(item.getDateEnd(), "yyyy-MM-dd");
                if (beginDate.before(inputBeginDate) && endDate.after(inputBeginDate)) {
                    return false;
                }
                if (endDate.after(inputEndDate) && beginDate.before(inputEndDate)) {
                    return false;
                }
                if (beginDate.equals(inputBeginDate)) {
                    return false;
                }
                if (endDate.equals(inputEndDate)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 开始日期是否大于结束日期
     *
     * @param dateStart
     * @param dateEnd
     * @return
     * @throws ParseException
     */
    private boolean isNewYear(String dateStart, String dateEnd) throws ParseException {
        SimpleDateFormat df = new SimpleDateFormat("MM-dd");
        Date dt1 = df.parse(dateStart);
        Date dt2 = df.parse(dateEnd);
        return dt1.after(dt2);
    }

    public static List<String> getMonthBetween(String minDate, String maxDate, boolean isContain) throws ParseException {
        String[] minDateStr = minDate.split("-");
        minDate = minDateStr[0] + "-" + minDateStr[1];
        String[] maxDateStr = maxDate.split("-");
        maxDate = maxDateStr[0] + "-" + maxDateStr[1];
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();
        min.setTime(sdf.parse(minDate));
        min.set(min.get(1), min.get(2), 1);
        max.setTime(sdf.parse(maxDate));
        max.set(max.get(1), max.get(2), 2);
        Calendar curr = min;
        while (curr.before(max)) {
            String[] dateArr = sdf.format(curr.getTime()).split("-");
            if (isContain) {
                result.add(dateArr[1]);
            } else if (!minDate.equals(sdf.format(curr.getTime())) && !maxDate.equals(sdf.format(curr.getTime()))) {
                result.add(dateArr[1]);
            }
            curr.add(2, 1);
        }
        return result;
    }
}
